<?php

namespace app\api\controller;

use app\common\controller\Api;
use app\common\model\Goods;
use app\common\model\Order;
use app\common\model\OrderProducts;
use app\common\model\Address;
use think\Config;
use think\Db;
use think\Exception;
use think\model\Collection;
use think\Request;
use app\common\model\Cutfare;
use think\Validate;

/**
 * 领奖记录接口
 * 领奖流程
 * 开奖中奖 is_opne = 1 is_win = 1 未领奖 status = 0
 * 去领奖 生成订单 order_sn 正常state = 1 未支付pay_state = 0  |  弃奖 status = 2
 * 付款 pay_state = 1 已领奖 status = 1 未发货ship_state = 0 | 未付款 自动弃奖 status = 2  取消state=3 expiretime
 * 后台发货 ship_state = 1
 * 用户确认收货 已收货ship_state = 2 已完成state = 2 |自动确认收货
 */
class Prizedraw extends Api
{
    protected $noNeedLogin = [];
    protected $noNeedRight = ['*'];

    protected $model = null;

    public function __construct()
    {
        parent::__construct();
        $this->model = new \app\common\model\PrizeDraw;
    }

    public function index()
    {
        $this->success('i18n:62');
    }

    /**
     * 领奖信息管理 获取列表
     * @throws \think\exception\DbException
     */
    public function winList(){

        //获取tab状态 all全部 shipped已发货 noprize未领奖 giveup已弃奖
        $status = $this->request->request('status');

        $map = [
            'is_opened' => 1,
            'is_win'    => 1,
            'fa_prize_draw.user_id'   => $this->auth->id,
        ];

        switch ($status){
            case 'noprize':
                //未领奖
                $map['status'] = 0;
                break;
            case 'shipped':
                //已领奖
                $map['status'] = 1;
                //已付款
                $map['order.pay_state'] = 1;
                //已发货
                $map['order.ship_state'] = ['neq',0];
                break;
            case 'giveup':
                //已弃奖
                $map['status'] = 2;
                break;
            default:
                break;

        }

        /*$data = $this->model
            ->with(['goods'=>function($query){
                $query->field('id,name,price,image');
            }])
            ->alias('p')
            ->join('fa_order d','d.order_sn=p.order_sn','LEFT')
            ->field('p.id,p.prize_id,p.user_id,p.opentime,p.goods_id,p.price,p.num,p.status,p.order_sn,d.state as order_state')
            ->where($map)
            ->paginate(10);*/

        //TODO
        //with 查询关联表内的字段 关联设置 setEagerlyType = 0 join 如果多级嵌套关联 需去掉setEagerlyType() 否则只显示一级
        //with + alias 别名无效 需要 join
        //主表增加with内字段作为查询条件 with方法名.字段 如 order.state,主表字段 需要加上主表全名前缀 如 fa_prize_draw.id
        //with内查询条件，过滤with方法中的 内容
        //field 在with 前 有效 后无效
        $data = $this->model
            ->field('id,prize_id,user_id,opentime,goods_id,price,num,status,order_sn')
            ->with(['goods'=>function($query){
                $query->withfield('id,name,price,image');
            }])
            ->with(['order'=>function($query){
                $query->withfield('id,order_sn,state,pay_state,ship_state,order_amount,prize_amount,freight_fee');
            }])
            ->where($map)
            ->paginate(10);

        //不执行 返回sql
        //->fetchSql(true)->select();
        //echo $data;exit;

        $statusDict = [
            0 => 'i18n:11',
            1 => 'i18n:161',
            2 => 'i18n:51',
        ];

        //处理data
        foreach ($data as $k=>$v){
            $data[$k]['goods']['image'] = getRealUrl($v['goods']['image']);

            //返回领奖信息
            $tips = '';
            if ($v['status'] == 0) {
                if ($v['order_sn']){
                    $tips = 'i18n:185';
                }else{
                    $tips = 'i18n:11';
                }
            }elseif ($v['status'] == 1){
                if ($v['order']['state'] == 1){
                    if ($v['order']['pay_state'] == 1){
                        if ($v['order']['ship_state'] == 1){
                            $tips = 'i18n:96';
                        }else{
                            $tips = 'i18n:184';
                        }
                    }
                }elseif ($v['order']['state'] == 2){
                    $tips = 'i18n:61';
                }elseif ($v['order']['state'] == 3){
                    $tips = 'i18n:183';
                }
            }elseif ($v['status'] == 2){
                $tips = 'i18n:51';
            }

            $data[$k]['tips']  = $tips;
        }

        //$data['status'] = $status;
        $this->success('i18n:62',compact('data','status'));
    }

    public function detail(){
        $id = $this->request->request('id');

        if (!$id) $this->error('i18n:182');

        $user_id = $this->auth->id;
        $map = [
            'user_id' => $user_id,
        ];
        $data = $this->model
            ->with(['goods'=>function($query){
                $query->field(['id,name,price,brief,image,images,intro_content,spes_desc,params,is_nomal_virtual'])
                    ->with(['products'=>function($query2){
                        $query2->field('id,goods_id,price,is_defalut,image,sn,stock,spes_desc');
                    }]);
            }])
            ->field('id,prize_id,opentime,goods_id,price,num,status')
            ->with(['cutfare' => function($query){
                $query->field('type,prize_draw_id,user_id,discount');
            }])
            ->where($map)
            ->find($id);

        if (!$data) $this->error('i18n:160');

        $data = $data->toArray();

        //TODO 直接显示组合
        //获取默认货品和多规格参数
        /*$product = $this->getProductsInfo($data['goods']);
        $data['goods']['products'] = $product;*/

        //图片相对地址转绝对地址 begin

        /*if ($data['image']) {
            $data['image'] = getRealUrl($data['image']);
        }*/

        if ($data['goods']['image']) {
            $data['goods']['image'] = getRealUrl($data['goods']['image']);
        }

        if ($data['goods']['images']) {
            $images = explode(',',$data['goods']['images']);
            foreach ($images as $k =>$v){
                $images[$k] = getRealUrl($v);
            }
            $data['goods']['images'] = $images;
        }

        //编辑框图片转绝对地址
        if (isset($data['goods']['intro_content'])) {
            preg_match_all('/(?<=img.src=").*?(?=")/', $data['goods']['intro_content'], $out, PREG_PATTERN_ORDER);      //正则匹配img标签的src属性，返回二维数组
            if (!empty($out)) {
                foreach ($out as $v) {
                    foreach ($v as $j) {
                        $url = getRealUrl($j);
                        $data['goods']['intro_content'] = str_replace($j, $url, $data['goods']['intro_content']);   //替换相对路径为绝对路径
                    }
                }
            }
        }
        //图片处理 end
        $request = Request::instance();
        $domain = $request->domain();
        $data['goods']['intro_html'] = $domain . '/api/prize/toHtml?gid='.$data['goods_id'];

        //多规格参数
        //$data['goods']['spes_desc'] = unserialize($data['goods']['spes_desc']);

        //固定参数
        $params = unserialize($data['goods']['params']);
        if (is_array($params)){
            foreach($params as $k=>$v){
                if (is_array($v)){
                    $params[$k] = implode('|',$v);
                }
            }
        }
        $data['goods']['params'] = $params;

        //TODO 运费默认 10 通过后台设置
        if (Config::get('site.freight_fee') > 0){
            $freight_fee = Config::get('site.freight_fee');
        }else{
            //免运费
            $freight_fee = 0;
        }
        $data['goods']['freight'] = $freight_fee;

        //获取剩余砍邮费次数 默认3次
        $data['residue'] = 3 - count($data['cutfare']);

        $this->success('i18n:62',$data);
    }

    /**
     * 领取接口 生产订单 修改状态
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function receive()
    {
        //prize_draw id
        $id = $this->request->request('id');
        $address_id = $this->request->request('address_id');
        $products_id = $this->request->request('products_id');
        //TODO 传参规格

        //校验数据 BEGIN
        $param = [
            'id'    => $id,
            'address_id'   => $address_id,
            'products_id'  => $products_id,
        ];

        $rule = [
            'id'     => 'require',
            'address_id' => 'require',
            'products_id'   => 'require',
        ];

        $msg = [
            'id.require'        => 'i18n:181',
            'address_id.require'=> 'i18n:180',
            'products_id.require'=> 'i18n:179',
        ];

        $validate = new Validate($rule, $msg);
        $result = $validate->check($param);
        if (!$result) {
            $this->error($validate->getError());
            return false;
        }
        //校验数据 END

        $map = [
            'user_id'   => $this->auth->id,
            'is_opened' => 1,
            'is_win'    => 1,
            'status'    => 0,
            'id'        => $id,
        ];
        $data = $this->model
            ->with(['goods'=>function($query){
                $query->field(['id,name,price,is_nomal_virtual,bn'])
                    ->with(['products'=>function($query2){
                        $query2->field('id,goods_id,price,is_defalut,image,sn,stock,spes_desc');
                    }]);
            }])
            ->with(['cutfare'=>function($query){
                //user_id > 0 砍邮费成功
                $query->field(['id,user_id,type,discount,prize_draw_id'])->where('user_id','>',0);
            }])
            ->where($map)
            ->find();

        if (!$data) $this->error('i18n:160');
        if ($data['order_sn']){
			$this->error('i18n:178');
		}

        //TODO 后台获取运费 先砍邮费 然后生成订单
        if (Config::get('site.freight_fee') > 0){
            $freight = Config::get('site.freight_fee');
        }else{
            //免运费
            $freight = 0;
        }

        //虚拟商品运费为0
        if ($data['goods']['is_nomal_virtual'] == 2) $freight = 0;

        //计算砍掉多少邮费
        $discount = 0;
        foreach($data['cutfare'] as $k => $v){
            $discount += $v['discount'] * 100;
        }
        //如果邮费为0 则不减 砍邮费
        $freight = $freight ? ($freight * 100 - $discount)/100 : 0;

        //生成主订单号
        $order_sn = get_sn(1);
        //整理order_products 数据

        //TODO 传递 productid 获取products
        //$products = $data['goods']['products'][0];
        $products = [];
        foreach ($data['goods']['products'] as $k => $v){
            if ($v['id'] == $products_id){
                $products = $v;
            }
        }
        if (!$products){
            $this->error('i18n:177');
        }

        //订单商品货品详情
        $orderProductsData = [
            'order_sn'  => $order_sn,
            'goods_id'  => $data['goods_id'],
            'products_id'  => $products['id'],
            'bn'        => $data['goods']['bn'], //商品编码
            'sn'        => $products['sn'], //货品编码
            'name'      => $data['goods']['name'], //商品名称
            'spes_desc' => $products['spes_desc'], //货品规格
            'price'     => $products['price'], //货品单价（原价）
            'num'       => $data['num'], //数量
            'amount'    => bcmul($data['price'],$data['num']), //奖品价格乘以数量
            'image'     => $products['image'],
            'is_nomal_virtual'  => $data['goods']['is_nomal_virtual'], //是否虚拟商品
        ];

        //生成订单 获取订单id 更新prize_draw 的 订单编号 更新商品冻结库存
        $orderModel = new Order();
        $orderProductsModel = new OrderProducts();
        $addressModel = new Address();
        $goodsModel = new Goods();

        //TODO 根据address_id 获取收货地址具体信息 防止发生改动
        $address_where = [
            'id'        => $address_id,
            'user_id'   => $this->auth->id,
        ];
        $address = $addressModel->where($address_where)->find();
        if (!$address) $this->error('i18n:176');

        //应付款 订单总额 奖品总价格 + 运费
        $order_amount = bcadd($data['price'],$freight,2);
        //整理订单数据
        $orderParam = [
            'order_sn'      => $order_sn,
            'user_id'       => $this->auth->id,
            'ip'            => $this->request->ip(0,true),
            'address_id'    => $address_id,    //收货地址id
            'order_amount'  => $order_amount,  //应付款 订单总额 奖品总价格 + 运费
            'prize_amount'  => $data['price'], //奖品总价格
            'freight_fee'   => $freight, //邮费运费
            'state'         => 1, //订单状态 1=正常 2=完成 3=取消
            'pay_state'     => 0, //支付状态 0=待付款 1=已付款
            'ship_state'    => 0, //发货状态 0=待发货 1=已发货 3=已收货
            'payment'       => 0, //已付款金额（实付金额）
            'ship_name'     => $address['name'],
            'ship_mobile'   => $address['mobile'],
            'ship_area'     => $address['area'],
            'ship_detail'   => $address['detail'],
        ];
        /*echo '<pre>';
        var_dump($orderProductsData);exit;*/

        $prizeDrawParam = [
            'status'    => 0,  //默认需要支付，则归类未领奖
            'order_sn'  => $order_sn,
            'updatetime'=> time(),
        ];

        //应付款 为0 则state 支付状态 直接为1
        if ($order_amount == 0) {
            $orderParam['pay_state'] = 1;         //支付状态
            $orderParam['payment_time'] = time(); //支付时间
            $prizeDrawParam['status'] = 1;        //不需要支付 更新prize_draw status = 1 归类已领奖
        }
        //$this->success('',$orderParam);
        //如果应付款 = 0，state 直接为支付完成状态

        Db::startTrans();
        try {
            //生成订单
            $orderModel->save($orderParam);
            //生成orderproducts
            $orderProductsModel->save($orderProductsData);
            //更新prizedraw order_sn
            $this->model->where($map)->update($prizeDrawParam);
            //提交订单增加冻结库存
            $ret = $goodsModel->changeStock($products_id,'order',$data['num']);

            Db::commit();
        }catch (Exception $e){
            Db::rollback();
            $this->error($e->getMessage());
        }

        $this->success('i18n:175',[
            'prize_draw_id' => $id,
            'order_sn' => $order_sn,
            'money' => $orderParam['order_amount'], //应付款 订单总额 奖品总价格 + 运费
            'state' => $orderParam['state'], //订单状态 1=正常 2=完成 3=取消
            'pay_state' => $orderParam['pay_state'], //支付状态 0=待付款 1=已付款
            'status'    => 1, //1=已领奖 prizedraw
        ]);
    }


    /**
     * 放弃领奖
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function giveUp(){
        //prize_draw id
        $id = $this->request->request('id');

        $map = [
            'user_id'   => $this->auth->id,
            'is_opened' => 1,
            'is_win'    => 1,
            'status'    => 0,
            'id'        => $id,
        ];
        $data = $this->model
            ->where($map)
            ->find();

        if (!$data) $this->error('i18n:160');

        //更新状态 弃奖 status 0未领 1已领 2弃奖
        $result = $this->model->where($map)->update([
            'status' => 2,
            'updatetime' => time(),
        ]);
        if (!$result) $this->error('i18n:174');

        $this->success('i18n:173',['id' => $data['id']]);
    }


    public function getProductsInfo($goods = []){

        $product = [];

        //如果是多规格商品，算多规格
        if ($goods['spes_desc']) {
            $defaultSpec = [];
            $spesDesc    = unserialize($goods['spes_desc']);

            foreach ($goods['products'] as $k => $v){
                if ($v['is_defalut']){
                    $product = $v;
                    unset($goods['products'][$k]);
                }
            }

            //设置on的效果
            $productSpesDesc = getProductSpesDesc($product['spes_desc']);
            foreach ((array)$spesDesc as $k => $v) {
                foreach ((array)$v as $j) {
                    $defaultSpec[$k][$j]['name'] = $j;
                    if ($productSpesDesc[$k] == $j) {
                        $defaultSpec[$k][$j]['is_default'] = true;
                    } else {
                        $defaultSpec[$k][$j]['product_id'] = 0;
                    }
                }
            }

            //取出刨除去当前id的其他兄弟货品
            $product_list = $goods['products'] ?? [];

            foreach ($product_list as $k => $v) {
                $product_list[$k]['temp_spes_desc'] = getProductSpesDesc($v['spes_desc']);
            }
            //遍历二维多规格信息，设置货品id
            foreach ($defaultSpec as $k => $j) {
                foreach ($j as $v => $l) {
                    //如果是默认选中的，不需要找货品信息
                    if (isset($l['is_default'])) {
                        continue;
                    }
                    $tempProductSpesDesc     = $productSpesDesc;
                    $tempProductSpesDesc[$k] = $v;
                    //循环所有货品，找到对应的多规格
                    foreach ($product_list as $a) {
                        if (!array_diff_assoc($a['temp_spes_desc'], $tempProductSpesDesc)) {
                            $defaultSpec[$k][$v]['product_id'] = $a['id'];
                            break;           //找到了，就不循环剩下的货品了，没意义
                        }
                    }
                }
            }
            $product['default_spes_desc'] = $defaultSpec;
        }

        return $product;
    }
}
